import math
import matplotlib.pyplot as plt

def bresenham(x0, y0, x1, y1):
    points = []  # 存储直线上的点
    dx = abs(x1 - x0)
    dy = abs(y1 - y0)
    sx = 1 if x0 < x1 else -1
    sy = 1 if y0 < y1 else -1
    err = dx - dy

    while True:
        points.append((x0, y0))  # 记录当前点
        if x0 == x1 and y0 == y1:
            break
        e2 = 2 * err
        if e2 > -dy:
            err -= dy
            x0 += sx
        if e2 < dx:
            err += dx
            y0 += sy

    return points

def find_boundary_intersection(x0, y0, angle, width, height):
    # 计算方向向量
    dx = math.cos(math.radians(angle))
    dy = math.sin(math.radians(angle))

    # 存储交点
    intersections = []

    # 检查与左边界 (x = 0)
    if dx != 0:  # 避免除以零
        t = -x0 / dx
        if t > 0:  # 确保交点在直线的前进方向
            y = y0 + t * dy
            if 0 <= y < height:
                intersections.append((0, int(round(y))))

    # 检查与右边界 (x = width-1)
    if dx != 0:
        t = (width - 1 - x0) / dx
        if t > 0:  # 确保交点在直线的前进方向
            y = y0 + t * dy
            if 0 <= y < height:
                intersections.append((width - 1, int(round(y))))

    # 检查与上边界 (y = 0)
    if dy != 0:
        t = -y0 / dy
        if t > 0:  # 确保交点在直线的前进方向
            x = x0 + t * dx
            if 0 <= x < width:
                intersections.append((int(round(x)), 0))

    # 检查与下边界 (y = height-1)
    if dy != 0:
        t = (height - 1 - y0) / dy
        if t > 0:  # 确保交点在直线的前进方向
            x = x0 + t * dx
            if 0 <= x < width:
                intersections.append((int(round(x)), height - 1))

    # 选择距离起始点最近的交点
    closest_point = None
    min_distance = float('inf')
    for x, y in intersections:
        distance = math.sqrt((x - x0) ** 2 + (y - y0) ** 2)
        if distance < min_distance:
            min_distance = distance
            closest_point = (x, y)

    return closest_point


def draw_line_to_boundary(x0, y0, angle, width, height):
    # 找到终点
    end_point = find_boundary_intersection(x0, y0, angle, width, height)
    if end_point is None:
        return []  # 没有交点，返回空
    x1, y1 = end_point

    # 使用 Bresenham 算法绘制直线
    return bresenham(x0, y0, x1, y1)

def visualize_line(x0, y0, angle, width, height):
    # 获取直线上的点
    line_points = draw_line_to_boundary(x0, y0, angle, width, height)
    
    # 提取 x 和 y 坐标
    x_coords, y_coords = zip(*line_points)

    # 绘制图像
    plt.figure(figsize=(8, 8))
    plt.plot(x_coords, y_coords, marker='o', color='blue', label='Bresenham Line')
    plt.scatter([x0], [y0], color='red', label='Start Point')  # 起始点
    plt.xlim(0, width)
    plt.ylim(0, height)
    # plt.gca().invert_yaxis()  # 符合图形学中y轴向下的习惯
    plt.grid(True)
    plt.legend()
    plt.title(f"Bresenham Line (Angle: {angle}°)")
    plt.xlabel("X")
    plt.ylabel("Y")
    
    # 根据角度生成唯一的文件名
    filename = f'bresenham_angle_{angle}.jpg'
    plt.savefig(filename, dpi=300, bbox_inches='tight')  # 保存为高分辨率图像
    plt.close()  # 关闭当前图像，避免重复绘制


import matplotlib.pyplot as plt

def visualize_line1(x0, y0, angle, width, height):
    # 获取直线上的点
    line_points = draw_line_to_boundary(x0, y0, angle, width, height)
    
    # 提取 x 和 y 坐标
    x_coords, y_coords = zip(*line_points)

    # 绘制图像
    plt.figure(figsize=(8, 8))
    plt.plot(y_coords, x_coords, marker='o', color='blue', label='Bresenham Line')  # 注意这里交换了 x 和 y
    plt.scatter([y0], [x0], color='red', label='Start Point')  # 起始点
    plt.xlim(0, height)  # 横轴为 y，范围为高度
    plt.ylim(0, width)   # 纵轴为 x，范围为宽度
    plt.gca().invert_yaxis()  # 纵轴（x 轴）上小下大
    plt.grid(True)
    plt.legend()
    plt.title(f"Bresenham Line (Angle: {angle}°)")
    plt.xlabel("Y")  # 横轴为 Y
    plt.ylabel("X")  # 纵轴为 X
    
    # 根据角度生成唯一的文件名
    filename = f'bresenham_angle_{angle}.jpg'
    plt.savefig(filename, dpi=300, bbox_inches='tight')  # 保存为高分辨率图像
    plt.close()  # 关闭当前图像，避免重复绘制

# 测试：从点 (50, 50) 出发，角度为 0° 到 360°，屏幕大小为 100x100
if __name__ == '__main__':
    # angles = [0, 45, 90, 135, 180, 225, 270, 315, 360]
    angles = [0, 45, 90, 135, 180, 225, 270, 315, 360]
    angles = [-45, -90, -135, -180]
    # angles = [135]
    # angles = [0]
    for angle in angles:
        visualize_line1(50, 50, angle, 100, 100)
        print(f"Line with angle {angle}° saved as 'bresenham_angle_{angle}.jpg'")
